/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.radaction.DAO;

import br.com.radaction.DTO.Avaliacao;

import br.com.radaction.DTO.Disciplina;

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.Statement;
import java.sql.ResultSet;

import java.sql.SQLException;

import java.util.ArrayList;
import java.util.List;

/**
 * Classe para conectar com o SGBD e fazer as operações de CRUD
 * Create,Retrieve,Update e Delete
 * @author robson
 */
public class AvaliacaoDAO {

    private Connection conexao;

    /**
     * Construtor único, para garantir a existência de uma conexão com um SGBD
     * @param conexao Connection já aberta com um SGBD
     */
    public AvaliacaoDAO(Connection conexao) {
        this.conexao = conexao;
    }

    /**
     * Se a avaliação for válida, este método irá fazer o INSERT no SGBD.
     * O Código será inserido pela Sequência e será colocado novamente no objeto Avaliacao
     * @param av Avaliacao a ser inserida
     * @throws java.sql.SQLException Qualquer erro entre o Sistema e o Banco será devolvido nesta Exceção
     */
    public void create(Avaliacao av) throws SQLException {
        if (this.valida(av)) {
            String query = "INSERT INTO AVALIACAO (COD,TAREFA,DESCRICAO,CODDISCIPLINA,DATA,FLGESTADO)" +
                    "VALUES (NEXTVAL('seqAvaliacao'),?,?,?,?,?)";
            PreparedStatement pst = this.conexao.prepareStatement(query);
            pst.setString(1, av.getTarefa());
            pst.setString(2, av.getDescricao());
            pst.setInt(3, av.getDisciplina().getCod());
            Date dt = new Date(av.getData().getTime());
            pst.setDate(4, dt);//Verificar 

            String flag;
            if (av.getFlgConcluida()) {
                flag = "V";//tarefa concluída

            } else {
                flag = "F";//tarefa não concluída

            }
            pst.setString(5, flag);
            pst.executeUpdate();
            Statement st = this.conexao.createStatement();
            ResultSet rs = st.executeQuery("SELECT CURRVAL('seqAvaliacao')");
            if (rs.next()) {
                av.setCod(rs.getInt(1));
            }
            rs.close();
            st.close();
            pst.close();
        }
    }

    /**
     * Retorna a avaliação(tarefa) do SGBD de acordo com o código da tarefa recebido.
     * @param av Avaliacao a ser carregado do SGBD
     * @return Avaliacao do SGBD
     * @throws java.sql.SQLException Qualquer erro entre o Sistema e o Banco será devolvido nesta Exceção
     */
    public Avaliacao retrieve(Avaliacao av) throws SQLException {
        Avaliacao avRet = new Avaliacao();
        String sql = "SELECT COD,TAREFA,DESCRICAO,CODDISCIPLINA,DATA,FLGESTADO FROM AVALIACAO WHERE COD=?";
        PreparedStatement pst = this.conexao.prepareStatement(sql);
        pst.setInt(1, av.getCod());
        ResultSet rs = pst.executeQuery();
        if (rs.next()) {
            avRet.setCod(rs.getInt("COD"));
            avRet.setTarefa(rs.getString("TAREFA"));
            avRet.setDescricao(rs.getString("DESCRICAO"));
            Disciplina disciplina = new Disciplina(rs.getInt("CODDISCIPLINA"));
            DisciplinaDAO dDAO = new DisciplinaDAO(conexao);
            disciplina = dDAO.retrieve(disciplina);
            avRet.setDisciplina(disciplina);
            avRet.setData(rs.getDate("DATA"));
            if (rs.getString("FLGESTADO").equals("V")) {
                avRet.setConcluida(true);//tarefa não conluída

            } else {
                avRet.setConcluida(false);//tarefa concluída

            }
        }
        rs.close();
        pst.close();
        return avRet;
    }

    /**
     * Atualiza a avaliação no SGBD.
     * @param av Avaliacao a ser atualizada no SGBD
     * @throws java.sql.SQLException Qualquer erro entre o Sistema e o Banco será devolvido nesta Exceção
     */
    public void update(Avaliacao av) throws SQLException {
        if (this.valida(av)) {
            String sql = "UPDATE AVALIACAO SET TAREFA=?, DESCRICAO=?, CODDISCIPLINA=?, DATA=?, FLGESTADO=? WHERE COD=?";
            PreparedStatement pst = this.conexao.prepareStatement(sql);
            pst.setString(1, av.getTarefa());
            pst.setString(2, av.getDescricao());
            pst.setInt(3, av.getDisciplina().getCod());
            Date dt = new Date(av.getData().getTime());
            pst.setDate(4, dt);
            String flag;
            if (av.getFlgConcluida()) {
                flag = "V";
            } else {
                flag = "F";
            }
            pst.setString(5, flag);
            pst.setInt(6, av.getCod());
            pst.executeUpdate();
            pst.close();
        }
    }

    /**
     * Remove do SGBD a avaliação conforme o código presente na avaliacao passada como argumento
     * @param av Avaliacao a ser excluída. Necessita apenas do atributo COD
     * @throws java.sql.SQLException Qualquer erro entre o Sistema e o Banco será devolvido nesta Exceção
     */
    public void delete(Avaliacao av) throws SQLException {
        String query = "DELETE FROM AVALIACAO WHERE COD=?";
        PreparedStatement pst = this.conexao.prepareStatement(query);
        pst.setInt(1, av.getCod());
        pst.executeUpdate();
        pst.close();
    }

    /**
     * Retorna uma Lista com todas as Avaliações cadastrados no SGBD.
     * @return Lista com as avaliações
     * @throws java.sql.SQLException Qualquer erro entre o Sistema e o Banco será devolvido nesta Exceção
     */
    public List<Avaliacao> listaTodos() throws SQLException {
        List<Avaliacao> lista = new ArrayList<Avaliacao>();
        String query = "SELECT COD,TAREFA,DESCRICAO,CODDISCIPLINA,DATA,FLGESTADO FROM AVALIACAO ORDER BY DATA";
        Statement st = this.conexao.createStatement();
        ResultSet rs = st.executeQuery(query);
        while (rs.next()) {
            Avaliacao av = new Avaliacao(rs.getInt("COD"));
            av.setTarefa(rs.getString("TAREFA"));
            av.setDescricao(rs.getString("DESCRICAO"));
            av.setData(rs.getDate("DATA"));

            if (rs.getString("FLGESTADO").equals("V")) {
                av.setConcluida(true);//tarefa concluída

            } else {
                av.setConcluida(false);//tarefa não concluída

            }

            DisciplinaDAO dDAO = new DisciplinaDAO(conexao);
            Disciplina disciplina = new Disciplina(rs.getInt("CODDISCIPLINA"));
            disciplina = dDAO.retrieve(disciplina);
            av.setDisciplina(disciplina);
            lista.add(av);
        }
        rs.close();
        st.close();
        return lista;
    }

    public List<Avaliacao> listaTodos(String dataInicial, String dataFinal) throws SQLException {
        List<Avaliacao> lista = new ArrayList<Avaliacao>();
        String query = "SELECT COD,TAREFA,DESCRICAO,CODDISCIPLINA,DATA,FLGESTADO FROM AVALIACAO " +
                "WHERE DATA BETWEEN '" + dataInicial + "' AND '" + dataFinal +
                "'ORDER BY DATA";
        Statement st = this.conexao.createStatement();
        ResultSet rs = st.executeQuery(query);
        while (rs.next()) {
            Avaliacao av = new Avaliacao(rs.getInt("COD"));
            av.setTarefa(rs.getString("TAREFA"));
            av.setDescricao(rs.getString("DESCRICAO"));
            av.setData(rs.getDate("DATA"));

            if (rs.getString("FLGESTADO").equals("V")) {
                av.setConcluida(true);//tarefa concluída

            } else {
                av.setConcluida(false);//tarefa não concluída

            }

            DisciplinaDAO dDAO = new DisciplinaDAO(conexao);
            Disciplina disciplina = new Disciplina(rs.getInt("CODDISCIPLINA"));
            disciplina = dDAO.retrieve(disciplina);
            av.setDisciplina(disciplina);
            lista.add(av);
        }
        rs.close();
        st.close();
        return lista;
    }

    /**
     * Aplica os testes para as regras de negócio. 
     * @param av Avaliacao a ser testada
     * @return true se a Avaliacao atende as regras de negócio, ou false em caso contrário.
     */
    public boolean valida(Avaliacao av) {
        boolean ret = false;
        if (av != null) {
            ret = true;
        }
        return ret;
    }
}
